const {
    ShiftSelectableClassNames,
    MultiSelectableClassNames
} = require('./config');

class Selected {

    static className() {
        return 'Selected';
    }

    constructor() {
    }

    get selectedObjectClassName() {
        return this._selectedObjectClassName;
    }

    set selectedObjectClassName(value) {
        this._selectedObjectClassName = value;
    }

    get currentSelectedObjectInfo() {
        return this._currentSelectedObjectInfo;
    }

    set currentSelectedObjectInfo(value) {
        this._currentSelectedObjectInfo = value;
    }

    get shiftSelectionStartObject() {
        return this._shiftSelectionStartObject;
    }

    set shiftSelectionStartObject(value) {
        this._shiftSelectionStartObject = value;
    }

    get shiftSelectionEndObject() {
        return this._shiftSelectionEndObject;
    }

    set shiftSelectionEndObject(value) {
        this._shiftSelectionEndObject = value;
    }

    get startYinFuIndex() {
        return this._startYinFuIndex;
    }

    set startYinFuIndex(value) {
        this._startYinFuIndex = value;
    }

    get endYinFuIndex() {
        return this._endYinFuIndex;
    }

    set endYinFuIndex(value) {
        this._endYinFuIndex = value;
    }

    /**
     * 被选中元素的数组
     * @returns {Array}
     */
    get items() {
        if (!this._items) {
            this._items = [];
        }
        return this._items;
    }

    /**
     * @param value {Array}
     */
    set items(value) {
        this._items = value;
    }


    /**
     * 被选中的元素发生改变之前的回调
     * @returns {*}
     */
    get onBeforeItemChanged() {
        return this._onBeforeItemChanged;
    }

    set onBeforeItemChanged(value) {
        this._onBeforeItemChanged = value;
    }

    /**
     * 被选中的元素发生改变之后的回调
     * @returns {*}
     */
    get onItemsChanged() {
        return this._onItemsChanged;
    }

    set onItemsChanged(value) {
        this._onItemsChanged = value;
    }

    /**
     * 插入被选中元素
     * @param itemOrItems 可以是单个元素，也可以是多个元素的数组
     */
    insertItemOrItems(itemOrItems) {
        this.onBeforeItemChanged && this.onBeforeItemChanged(this.items);
        if (Array.isNotEmpty(itemOrItems)) {
            this.items.pushFromArray(itemOrItems);
        } else if (itemOrItems) {
            this.items.push(itemOrItems);
        }
        this.onItemsChanged && this.onItemsChanged(this.items);
    }

    removeCurrentSelectedObject() {
        let currentSelect = this.currentSelectedObjectInfo;
        if (currentSelect && currentSelect.target && currentSelect.parent && this.items.length > 1
            && (currentSelect.target.className === 'MusicScoreXiaoJie' || currentSelect.target.className === 'MusicScoreYinFu' || currentSelect.target.className === 'MusicScoreYinFuContent')) {
            // 多选删除判断
            shared.editorManager.currentMusicScoreEditor.arrangeSelectedInfoData(this.items);
        } else if (currentSelect && currentSelect.target && currentSelect.parent) {
            let vueComponent = this.currentSelectedObjectInfo.target.getVUEComponent && this.currentSelectedObjectInfo.target.getVUEComponent();
            vueComponent && vueComponent.setSelected(false);
            this.currentSelectedObjectInfo.target.removeFromParent(this.currentSelectedObjectInfo.parent);
            this.setCurrentSelectedObjectInfo(null);
        } else {
            console.log('多选删除判断有问题');
        }
        // if (this.currentSelectedObjectInfo && this.currentSelectedObjectInfo.target && this.currentSelectedObjectInfo.parent) {
        //     let vueComponent = this.currentSelectedObjectInfo.target.getVUEComponent && this.currentSelectedObjectInfo.target.getVUEComponent();
        //     vueComponent && vueComponent.setSelected(false);
        //     this.currentSelectedObjectInfo.target.removeFromParent(this.currentSelectedObjectInfo.parent);
        //     this.setCurrentSelectedObjectInfo(null);
        // } else {
        //     this.items.forEach((item) => {
        //         item.removeFromParent();
        //     });
        // }
    }

    setCurrentSelectedObjectInfo(currentSelectedObjectInfo) {
        this.selectedObjectClassName = this.getSelectedObjectClassName(currentSelectedObjectInfo);
        this.currentSelectedObjectInfo = currentSelectedObjectInfo;
        this.setShiftSelectionStartObject(currentSelectedObjectInfo);
        this.clearItems();

        (MultiSelectableClassNames.includes(this.selectedObjectClassName) || ShiftSelectableClassNames.includes(this.selectedObjectClassName)) && this.items.pushOnce(currentSelectedObjectInfo.target);
        this.setSelectedMusicScoreXiaoJieInsertYinFuDisabled();
    }

    setShiftSelectionStartObject(currentSelectedObjectInfo) {
        if ((currentSelectedObjectInfo && currentSelectedObjectInfo.target && ShiftSelectableClassNames.includes(currentSelectedObjectInfo.target.className))
            || !currentSelectedObjectInfo) {
            this.shiftSelectionStartObject = currentSelectedObjectInfo;
        }
    }

    static getSelectedObjectClassName(object) {
        return object && object.target && object.target.className;
    }

    getSelectedObjectClassName(object) {
        return this.constructor.getSelectedObjectClassName(object);
    }

    setShiftSelectionEndObject(currentSelectedObjectInfo) {
        let className = this.getSelectedObjectClassName(currentSelectedObjectInfo);
        (this.selectedObjectClassName === 'MusicScoreYinFuContent' && className === 'MusicScoreYinFu') && (this.selectedObjectClassName = 'MusicScoreYinFu');
        if (className
            && this.shiftSelectionStartObject
            && (ShiftSelectableClassNames.indexOf(this.selectedObjectClassName) >= ShiftSelectableClassNames.indexOf(className))) {
            this.clearItems();
            // this.items.length > 0 && this.selectedObjectClassName === 'MusicScoreXiaoJie' && shared.currentSelected && shared.currentSelected.setInsertYinFuDisabled && shared.currentSelected.setInsertYinFuDisabled();
            this.shiftSelectionEndObject = currentSelectedObjectInfo;
            let startIndex = this.shiftSelectionStartObject.target.index;
            let endIndex = this.shiftSelectionEndObject.target.index;
            let startFuPuBiaoIndex = Math.min(startIndex.fuPuBiaoIndex, endIndex.fuPuBiaoIndex);
            let endFuPuBiaoIndex = Math.max(startIndex.fuPuBiaoIndex, endIndex.fuPuBiaoIndex);
            let startDanPuBiaoIndex = Math.min(startIndex.danPuBiaoIndex, endIndex.danPuBiaoIndex);
            let endDanPuBiaoIndex = Math.max(startIndex.danPuBiaoIndex, endIndex.danPuBiaoIndex);
            let handler = (item) => {
                let vueComponent = item.getVUEComponent();
                vueComponent.isSelected = true;
                this.items.push(item);
            };
            let fuPuBiaoEnumerater = (cb) => {
                let start = Math.min(startFuPuBiaoIndex, endFuPuBiaoIndex);
                let end = Math.max(startFuPuBiaoIndex, endFuPuBiaoIndex);
                for (let fuPuBiaoIndex = start; fuPuBiaoIndex <= end; fuPuBiaoIndex++) {
                    cb && cb(shared.editorManager.currentMusicScoreData.fuPuBiaoArray[fuPuBiaoIndex], start === fuPuBiaoIndex, end === fuPuBiaoIndex);
                }
            };
            let danPuBiaoEnumerater = (cb) => {
                fuPuBiaoEnumerater((musicScoreFuPuBiao, isStartMusicScoreFuPuBiao, isEndMusicScoreFuPuBiao) => {
                    let start = Math.min(startDanPuBiaoIndex, endDanPuBiaoIndex);
                    let end = Math.max(startDanPuBiaoIndex, endDanPuBiaoIndex);
                    for (let danPuBiaoIndex = start; danPuBiaoIndex <= end; danPuBiaoIndex++) {
                        cb && cb(musicScoreFuPuBiao.danPuBiaoArray[danPuBiaoIndex], isStartMusicScoreFuPuBiao, isEndMusicScoreFuPuBiao);
                    }
                });
            };
            let xiaoJieEnumerater = (cb) => {
                danPuBiaoEnumerater((musicScoreDanPuBiao, isStartMusicScoreFuPuBiao, isEndMusicScoreFuPuBiao) => {
                    let realStartIndex = startIndex.compare(endIndex) === CSComparisonResult.OrderedDescending ? endIndex : startIndex;
                    let realEndIndex = realStartIndex === startIndex ? endIndex : startIndex;
                    let start = isStartMusicScoreFuPuBiao ? realStartIndex.xiaoJieIndex : 0;
                    let end = isEndMusicScoreFuPuBiao ? realEndIndex.xiaoJieIndex : (musicScoreDanPuBiao.xiaoJieArray.length - 1);
                    for (let xiaoJieIndex = start; xiaoJieIndex <= end; xiaoJieIndex++) {
                        cb && cb(musicScoreDanPuBiao.xiaoJieArray[xiaoJieIndex], isStartMusicScoreFuPuBiao, isEndMusicScoreFuPuBiao, start, end, xiaoJieIndex);
                    }
                });
            };
            let yinFuEnumerater = (cb) => {
                xiaoJieEnumerater((musicScoreXiaoJie, isStartMusicScoreFuPuBiao, isEndMusicScoreFuPuBiao, currentStartXiaoJieIndex, currentEndXiaoJieIndex, xiaoJieIndex) => {
                    let isStartMusicScoreXiaoJie = isStartMusicScoreFuPuBiao && currentStartXiaoJieIndex === xiaoJieIndex;
                    let isEndMusicScoreXiaoJie = isEndMusicScoreFuPuBiao && currentEndXiaoJieIndex === xiaoJieIndex;
                    if (isStartMusicScoreXiaoJie || isEndMusicScoreXiaoJie) {
                        let tmpStartIndex = startIndex.clone();
                        tmpStartIndex.shengBuIndex = 0;
                        let tmpEndIndex = endIndex.clone();
                        tmpEndIndex.shengBuIndex = 0;
                        let realStartIndex = tmpStartIndex.compare(tmpEndIndex) === CSComparisonResult.OrderedDescending ? endIndex : startIndex;
                        let realEndIndex = realStartIndex === startIndex ? endIndex : startIndex;
                        let startShengBuIndex = isStartMusicScoreXiaoJie ? realStartIndex.shengBuIndex : 0;
                        let endShengBuIndex = isEndMusicScoreXiaoJie ? realEndIndex.shengBuIndex : 0;
                        let start = isStartMusicScoreXiaoJie ? realStartIndex.yinFuIndex : 0;
                        let end = isEndMusicScoreXiaoJie ? realEndIndex.yinFuIndex : (musicScoreXiaoJie.shengBuArray[endShengBuIndex].yinFuArray.length - 1);
                        let startShengBu = musicScoreXiaoJie.shengBuArray[startShengBuIndex] && musicScoreXiaoJie.shengBuArray[startShengBuIndex].yinFuArray.length ? musicScoreXiaoJie.shengBuArray[startShengBuIndex] : musicScoreXiaoJie.firstNotnullMusicScoreShengBu();
                        let endShengBu = musicScoreXiaoJie.shengBuArray[endShengBuIndex] && musicScoreXiaoJie.shengBuArray[endShengBuIndex].yinFuArray.length ? musicScoreXiaoJie.shengBuArray[endShengBuIndex] : musicScoreXiaoJie.firstNotnullMusicScoreShengBu();
                        let startYinFu = startShengBu.yinFuArray[start] || startShengBu.yinFuArray.lastObject();
                        let startYinFuObject = isStartMusicScoreXiaoJie && {};
                        let endYinFuObject = isEndMusicScoreXiaoJie && {};
                        let endYinFu = endShengBu.yinFuArray[end] || endShengBu.yinFuArray.lastObject();
                        let startShowTime = startYinFu ? startYinFu.showTime : 0;
                        let endShowTime = isEndMusicScoreXiaoJie && (endShengBu.yinFuArray.length !== realEndIndex.yinFuIndex + 1) ? (endYinFu ? (endYinFu.showTime + endYinFu.showDuration) : Infinity) : Infinity;
                        musicScoreXiaoJie.shengBuForEach((musicScoreShengBu, musicScoreShengBuIndex) => {
                            musicScoreShengBu.yinFuArray.forEach(musicScoreYinFu => {
                                if (startShowTime <= musicScoreYinFu.showTime && musicScoreYinFu.showTime < endShowTime && !musicScoreYinFu.containerYiYin) {
                                    // endYinFuObject && (endYinFuObject[musicScoreShengBuIndex] = musicScoreYinFu);
                                    // if (startYinFuObject && !startYinFuObject[musicScoreShengBuIndex]) {
                                    //     let musicScoreYiYin = musicScoreShengBu.yiYinObject[musicScoreYinFu.frontYiYin];
                                    //     if (musicScoreYiYin) {
                                    //         for (let i = musicScoreYiYin.startYinFuIndex.yinFuIndex; i <= musicScoreYiYin.endYinFuIndex.yinFuIndex; i++) {
                                    //             let yiYinMusicScoreYinFu = musicScoreShengBu.yinFuArray[i];
                                    //             cb && cb(yiYinMusicScoreYinFu);
                                    //         }
                                    //     }
                                    //     musicScoreYiYin = musicScoreShengBu.yiYinObject[musicScoreYinFu.containerYiYin];
                                    //     if (musicScoreYiYin && musicScoreYiYin.startYinFuId !== musicScoreYinFu.id) {
                                    //         for (let i = musicScoreYiYin.startYinFuIndex.yinFuIndex; i < musicScoreYinFu.index.yinFuIndex; i++) {
                                    //             let yiYinMusicScoreYinFu = musicScoreShengBu.yinFuArray[i];
                                    //             cb && cb(yiYinMusicScoreYinFu);
                                    //         }
                                    //     }
                                    //     startYinFuObject[musicScoreShengBuIndex] = musicScoreYinFu;
                                    // }

                                    cb && cb(musicScoreYinFu);
                                }
                            });
                        });
                    } else {
                        musicScoreXiaoJie.shengBuForEach(musicScoreShengBu => {
                            for (let yinFuIndex = 0; yinFuIndex < musicScoreShengBu.yinFuArray.length; yinFuIndex++) {
                                cb && cb(musicScoreShengBu.yinFuArray[yinFuIndex]);
                            }
                        });
                    }
                });
            };
            this.selectedObjectClassName === 'MusicScoreFuPuBiao' && fuPuBiaoEnumerater(handler);
            this.selectedObjectClassName === 'MusicScoreDanPuBiao' && danPuBiaoEnumerater(handler);
            this.selectedObjectClassName === 'MusicScoreXiaoJie' && xiaoJieEnumerater(handler);
            (this.selectedObjectClassName === 'MusicScoreYinFu' || this.selectedObjectClassName === 'MusicScoreYinFuContent') && yinFuEnumerater(handler);
        }
        this.setSelectedMusicScoreXiaoJieInsertYinFuDisabled();
    }

    setMultiSelectedObject(currentSelectedObjectInfo) {
        let className = this.getSelectedObjectClassName(currentSelectedObjectInfo);
        if (className && MultiSelectableClassNames.includes(className) && MultiSelectableClassNames.includes(this.selectedObjectClassName)) {
            let indexData = shared.editorManager.currentMusicScoreData.getDataWithIndex(currentSelectedObjectInfo.target.index);
            let object = null;
            if (this.selectedObjectClassName === 'MusicScoreFuPuBiao') {
                object = indexData.musicScoreFuPuBiao;
            } else if (this.selectedObjectClassName === 'MusicScoreDanPuBiao') {
                object = indexData.musicScoreDanPuBiao;
            } else if (this.selectedObjectClassName === 'MusicScoreXiaoJie') {
                object = indexData.musicScoreXiaoJie;
            } else if (this.selectedObjectClassName === 'MusicScoreYinFu') {
                object = indexData.musicScoreYinFu;
            } else if (this.selectedObjectClassName === 'MusicScoreYinFuContent') {
                object = indexData.musicScoreYinFuContent;
            }
            let vueComponent = object && object.getVUEComponent && object.getVUEComponent();
            if (vueComponent) {
                let isSelected = !vueComponent.isSelected;
                vueComponent.isSelected = isSelected;
                isSelected ? this.items.pushOnce(object) : this.items.removeObject(object);
                // this.items.length > 0 && this.selectedObjectClassName === 'MusicScoreXiaoJie' && shared.currentSelected && shared.currentSelected.setInsertYinFuDisabled && shared.currentSelected.setInsertYinFuDisabled();
            }
        }
    }

    /**
     * 清空被选中元素
     */
    clearItems() {
        this.onBeforeItemChanged && this.onBeforeItemChanged(this.items);
        this.items.forEach((element) => {
            let vueComponent = element && element.getVUEComponent && element.getVUEComponent();
            vueComponent && (vueComponent.isSelected = false);
        });
        this.items.removeAllObject();
        this.onItemsChanged && this.onItemsChanged(this.items);
    }

    setSelectedMusicScoreXiaoJieInsertYinFuDisabled() {
        let isSingle = this.items.length === 1;
        this.items.forEach((element) => {
            let vueComponent = element && element.getVUEComponent && element.getVUEComponent();
            element.className === 'MusicScoreXiaoJie' && vueComponent && (isSingle ? vueComponent.setInsertYinFuEnabled() : vueComponent.setInsertYinFuDisabled());
        });
    }

    //循环items操作事件
    selectItemsForEach(cb) {
        this.items.forEach((item) => {
            cb && cb(item);
        });
    }

    //插入音符符号循环判断
    distinguishSelectedType(cb) {
        if (this.items.length > 1) {
            this.items.forEach((item) => {
                cb && cb(item);
            });
        } else {
            let currentData = this.currentSelectedObjectInfo.target;
            cb && cb(currentData);
        }
    }

    currentSelectedTargetArray() {
        return this.items.length > 1 ? this.items : [this.currentSelectedObjectInfo.target];
    }

    currentSelectedParentArray() {
        return this.items.length > 1 ? this.items : [this.currentSelectedObjectInfo.parent];
    }
}

module.exports = {
    Selected
};
